package org.jeecg.modules.achachievestandarditem.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jdk.nashorn.internal.parser.JSONParser;
import org.jeecg.modules.achachievementstandard.entity.AchAchievementStandard;
import org.jeecg.modules.achachievementstandard.mapper.AchAchievementStandardMapper;
import org.jeecg.modules.achachievestandarditem.entity.AchAchieveStandardItem;
import org.jeecg.modules.achachievestandarditem.mapper.AchAchieveStandardItemMapper;
import org.jeecg.modules.achachievestandarditem.service.IAchAchieveStandardItemService;
import org.jeecg.modules.achachievestandarditem.vo.AchAchieveStandardItemVo;
import org.jeecg.modules.achexamination.entity.AchExamination;
import org.jeecg.modules.achexamination.mapper.AchExaminationMapper;
import org.jeecg.modules.achexaminationpaper.entity.AchExaminationPaper;
import org.jeecg.modules.achexaminationpaper.mapper.AchExaminationPaperMapper;
import org.jeecg.modules.achexaminationpaper.service.IAchExaminationPaperService;
import org.jeecg.modules.achexampaperprojectitem.entity.AchExamPaperProjectItem;
import org.jeecg.modules.achexampaperprojectitem.service.IAchExamPaperProjectItemService;
import org.jeecg.modules.relation.relachstandarddistribution.entity.RelAchStandardDistribution;
import org.jeecg.modules.relation.relachstandarddistribution.mapper.RelAchStandardDistributionMapper;
import org.jeecg.modules.relation.relachstandarddistribution.service.IRelAchStandardDistributionService;
import org.jeecg.modules.subject.entity.CouSubject;
import org.jeecg.modules.subject.mapper.CouSubjectMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @Description: ach_achieve_standard_item
 * @author: baochangrong
 * @Date: 2022-03-16
 * @Version: V1.0
 */
@Service
public class AchAchieveStandardItemServiceImpl extends ServiceImpl<AchAchieveStandardItemMapper, AchAchieveStandardItem> implements IAchAchieveStandardItemService {

    @Autowired
    AchAchieveStandardItemMapper achAchieveStandardItemMapper;
//    @Autowired
//    IAchAchieveStandardItemService achAchieveStandardItemService;

    @Autowired
    IRelAchStandardDistributionService distributionService;

    @Autowired
    AchAchievementStandardMapper standardMapper;

    @Autowired
    AchExaminationMapper examinationMapper;

    @Autowired
    CouSubjectMapper couSubjectMapper;

    @Autowired
    RelAchStandardDistributionMapper relDistributionMapper;

    @Autowired
    RelAchStandardDistributionMapper distributionMapper;

    @Autowired
    @Lazy //循环引用：achExaminationPaperServiceImpl中引用了achAchieveStandardItemServiceImpl
    IAchExaminationPaperService achExaminationPaperService;
    @Autowired
    IAchExamPaperProjectItemService achExamPaperProjectItemService;

    @Override
    /** 根据上级评分标准id获取标准明细记录 */
    public List<AchAchieveStandardItemVo> listBystandardId(String achievementStandardId, String tenantId) {
        List<AchAchieveStandardItemVo> achAchieveStandardItemVoList = achAchieveStandardItemMapper.listBystandardId(achievementStandardId, tenantId);
        return achAchieveStandardItemVoList;
    }

    @Override
    public IPage<AchAchieveStandardItemVo> queryAchievementsItemByRelObjIdType(Page<AchAchieveStandardItemVo> page, AchAchieveStandardItemVo achAchieveStandardItemVo) {
        List<AchAchieveStandardItemVo> list = achAchieveStandardItemMapper.listByAchievenmemtId(achAchieveStandardItemVo);
        return page.setRecords(list);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean createStandardItemByExamPaper(List<AchExaminationPaper> papers, String examId) {
        AchExamination examination = examinationMapper.selectById(examId);
        final String sysOrgCode = examination.getSysOrgCode();
        final String createBy = examination.getCreateBy();
        final String tenantId = examination.getTenantId();
        Map<String, Object> query = new HashMap<>();
        query.put("tenant_id", tenantId);
        query.put("del_flag", 0);
        List<CouSubject> couSubjects = couSubjectMapper.selectByMap(query);
        HashMap<String, CouSubject> subjectMap = new HashMap<>();
        couSubjects.forEach(item -> {
            subjectMap.put(item.getId(), item);
        });
        AchAchievementStandard newStandard = new AchAchievementStandard()
                .setAchievementStandardName(examination.getExaminationName() + "[计分规则]")
                .setAchievementStandardTtype(examination.getExaminationTtype())
                .setAchievementStandardPurpose("93")
                .setAchiStandPurposeType("9");
        BeanUtils.copyProperties(examination, newStandard);

        if (standardMapper.insert(newStandard) > 0) {
            try {
                final String standId = newStandard.getId();
                List<AchAchieveStandardItem> insertList = new ArrayList<>();
                papers.forEach(item -> {
                    insertList.add(new AchAchieveStandardItem().setAchievementStandardId("")
                            .setExaPapProItemCode(item.getId())
                            .setSubjectId(item.getSubjectId())
                            .setStandItemName(item.getExaminationPaperName())
                            .setStandItemAliasname(subjectMap.get(item.getSubjectId()).getSubjectName())
                            .setStandItemOrder(subjectMap.get(item.getSubjectId()).getSubjectOrder())
                            .setStandItemWeightCoefficient(1.0)
                            .setCreateBy(createBy)
                            .setTenantId(tenantId)
                            .setSysOrgCode(sysOrgCode)
                            .setAchievementStandardId(standId)
                            .setDelFlag(0)
                            .setIzOpen(1)
                    );
                });
                if (!saveBatch(insertList)) {
                    log.error("Batch insert AchAchieveStandardItems Failed...");
                    throw new RuntimeException();
                }
                /**
                 * Distribution Objet-Standard-Rules
                 */
                distributionService.save(new RelAchStandardDistribution()
                        .setAchievementStandardId(standId)
                        .setRelObjType("93")
                        .setRelObjId(examId)
                        .setTenantId(tenantId)
                        .setSysOrgCode(sysOrgCode)
                        .setPaperStandardEffective(1)
                );
                return true;
            } catch (RuntimeException e) {
                log.error(e.getMessage());
                throw new RuntimeException();
            }
        }
        log.error("Something failed ...");
        return false;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean resetStandardItemByExamPaper(String examId) {
        List<RelAchStandardDistribution> distributionList = distributionService.queryStandardIdByObjTypeId(examId, "93");
        if (distributionList.size() > 0) {
            try {
                distributionList.forEach(item -> {
                    List<AchAchievementStandard> achievementStandards = standardMapper.selectList(new QueryWrapper<AchAchievementStandard>().
                            likeRight("id", item.getAchievementStandardId()));
                    achievementStandards.forEach(achievementStandard -> {
                        if (achAchieveStandardItemMapper.deleteByAchievementStandardId(achievementStandard.getId()) > 0) {
                            if (standardMapper.deleteById(achievementStandard.getId()) > 0) {
                                if (relDistributionMapper.deleteById(item.getId()) < 1) {
                                    log.error("Delete RelAchStandardDistribution Failed...");
                                    throw new RuntimeException();
                                }
                            } else {
                                throw new RuntimeException();
                            }
                        }
                    });
                });
                return true;
            } catch (RuntimeException e) {
                log.error("Can't Reset The Items : " + e.getMessage());
            }
        }
        return false;

    }

    @Override
    public boolean cleanAchItems(String examId) {
        return distributionService.cleanAllItemsAndRules(examId);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int insertNewStandardItem(String json) {
        try {
            JSONObject jsonObject = JSON.parseObject(json);
            JSONObject jsonString = jsonObject.getJSONObject("json");
            String examId = jsonString.getString("examId");
            String test = jsonString.getString("item");
            JSONArray jsonArray = JSON.parseArray(test);
            AchExamination examination = examinationMapper.selectById(examId);
            JSONObject itemJson = jsonString.getJSONObject("standard");

            AchAchievementStandard standard = JSONObject.toJavaObject(itemJson, AchAchievementStandard.class);
//            StringBuffer sb = new StringBuffer().append(examination.getExaminationName()).append(standard.getAchievementStandardName());
//            standard.setAchievementStandardName(sb.toString());
            if (standardMapper.insert(standard) > 0) {
                ArrayList itemList = new ArrayList(jsonArray.size());
                for (Object o : jsonArray) {
                    JSONObject a = (JSONObject) o;
                    AchAchieveStandardItem standardItem = JSONObject.toJavaObject(a, AchAchieveStandardItem.class);
                    standardItem.setAchievementStandardId(standard.getId())
                            .setExaPapProItemCode(examId);
                    itemList.add(standardItem);
                }
                if (saveBatch(itemList)) {
                    RelAchStandardDistribution distribution = new RelAchStandardDistribution()
                            .setAchievementStandardId(standard.getId())
                            .setPaperStandardEffective(1)
                            .setRelObjType("92")
                            .setRelObjId(examId);
                    if (relDistributionMapper.insert(distribution) > 0) {
                        return 1;
                    }
                    throw new RuntimeException();
                } else {
                    throw new RuntimeException();
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new RuntimeException();
        }
        return 0;
    }

    @Override
    public void checkIsStandardItemEmpty(String standardId) {
        System.out.println(standardId);
        QueryWrapper<AchAchieveStandardItem> itemWrapper = new QueryWrapper<AchAchieveStandardItem>();
        itemWrapper.eq("del_flag", 0);
        itemWrapper.eq("achievement_standard_id", standardId);
        List<AchAchieveStandardItem> standardItems = list(itemWrapper);
        // size == 0 则全部清空
        if (standardItems.size() == 0) {
            Map<String, Object> deleteStandardMap = new HashMap<>();
            deleteStandardMap.put("id", standardId);
            deleteStandardMap.put("del_flag", 0);
            standardMapper.deleteByMap(deleteStandardMap);

            Map<String, Object> deleteRelDistributionMap = new HashMap<>();
            deleteRelDistributionMap.put("rel_obj_id", standardId);
            deleteRelDistributionMap.put("paper_standard_effective", 1);
            relDistributionMapper.deleteByMap(deleteRelDistributionMap);

            /**
             * 执行过逻辑删除对其进行物理删除
             */
            Map<String, Object> deleteItemMap = new HashMap<>();
            deleteItemMap.put("achievement_standard_id", standardId);
            deleteItemMap.put("del_flag", 1);
            achAchieveStandardItemMapper.deleteByMap(deleteItemMap);
        }
    }


    /**
     * 获取针对试卷总分项的标准
     */
    @Override
    public IPage<AchAchieveStandardItemVo> getAchExamPaperStandardItem(Page<AchAchieveStandardItemVo> page, String exaPapProItemCode, String tenantId) {
        List<AchAchieveStandardItemVo> achAchieveStandardItemVoList = achAchieveStandardItemMapper.getAchExamPaperStandardItem(exaPapProItemCode, tenantId);
        return page.setRecords(achAchieveStandardItemVoList);
    }


    /**
     * 快速添加
     */
    @Override
    public boolean speedAddStandardItem(JSONObject jsonObject, String tenantId) {
        String standardId = jsonObject.getString("standardId");//上级标准standardId
        String subjectId = jsonObject.getString("subjectId");//科目
        String examinationPaperId = jsonObject.getString("examinationPaperId");//试卷

        JSONArray paperStandardItemArray = jsonObject.getJSONArray("paperStandardItem");//总分的标准参数
        JSONArray paperItemStandardItemArray = jsonObject.getJSONArray("paperItemStandardItem");//题型的标准参数
        //开始依次新增-总分的标准参数
        int i = 0;//排序
        int CODE = 001;//本身编码
        //查询试卷
        AchExaminationPaper achExaminationPaper = achExaminationPaperService.getById(examinationPaperId);//试卷
        Double paperTotal = achExaminationPaper.getExaminationPaperFullMarks();//试卷总分(满分)
        //JSONArray直接可以遍历循环-总分相关的明细新增
        for (Object o : paperStandardItemArray) {
            JSONObject object = (JSONObject) o;//转换后才能取某一字段
            String itemDomainName = ((JSONObject) o).getString("itemDomainName");
            String itemDomainSubName = ((JSONObject) o).getString("itemDomainSubName");
            String itemDomainScore = ((JSONObject) o).getString("itemDomainScore");
            //分隔分数范围比率 如：itemDomainScore = "0-60",分割切转为浮点型0.0 和 0.6,standItemLowestRate = 0.0   standItemHighestRate = 0.6
            String str[] = itemDomainScore.split("-", 2);
            Double standItemLowestRate = Double.valueOf(str[0]);//取值范围最低比率 如：0.0
            Double standItemHighestRate = Double.valueOf(str[1]);//取值范围最高比率 如：0.6
            //依次给实体的属性set值
            AchAchieveStandardItem achAchieveStandardItem = new AchAchieveStandardItem();
            achAchieveStandardItem.setId(null);//清空id
            achAchieveStandardItem.setAchievementStandardId(standardId);//主要-上级标准
            achAchieveStandardItem.setSubjectId(subjectId);
            achAchieveStandardItem.setExaPapProItemCode(examinationPaperId);//主要：总分标准时-试卷ID，题型分项标准时-题项ID
            CODE = CODE + 1;
            achAchieveStandardItem.setStandItemCode(Integer.toString(CODE));
            achAchieveStandardItem.setStandItemName(itemDomainName + "（" + "总分" + "）");//段位名称
            achAchieveStandardItem.setStandItemAliasname(itemDomainSubName);//段位简称
            //取值范围 试卷满分-总分
            Double scoreMin = paperTotal * standItemLowestRate;//主要：计算后得最低比率对应的最低分数
            achAchieveStandardItem.setStandItemLowestScore(scoreMin);
            Double scoreMax = paperTotal * standItemHighestRate;//主要：计算后得最高比率对应的最高分数
            achAchieveStandardItem.setStandItemHighestScore(scoreMax);
            achAchieveStandardItem.setStandItemLowestRate(standItemLowestRate);//主要：最低比率 如：0.0
            achAchieveStandardItem.setStandItemHighestRate(standItemHighestRate);//主要：最高比率 如：0.6

            achAchieveStandardItem.setStandItemActualScore(null);//实际得分
            achAchieveStandardItem.setStandItSpecialRestrictions(null);//特殊限制（1无限制，2性别，3年级 4年龄，5预留）
            achAchieveStandardItem.setSitemSpecRestMaxvalue(null);//特殊限制数最大值（不含或小于）
            achAchieveStandardItem.setSitemSpecRestMinvalue(null);//特殊限制数最小值（含即大于等于或等于）
            achAchieveStandardItem.setStandItemFatherId("0");//上级项目id
            i = i + 1;
            achAchieveStandardItem.setStandItemOrder(i);//排序
            achAchieveStandardItem.setSysOrgCode(null);//部门编码
            achAchieveStandardItem.setTenantId(tenantId);
            achAchieveStandardItem.setDelFlag(0);
            achAchieveStandardItem.setIzOpen(1);
            boolean _statu = save(achAchieveStandardItem);
            if (!_statu) {
                return false;
            }
        }
        //JSONArray直接可以遍历循环-题型分项相关的明细新增
        //查询试卷的所有题型分项
        AchExamPaperProjectItem achExamPaperProjectItem = new AchExamPaperProjectItem();
        achExamPaperProjectItem.setExaminationPaperId(examinationPaperId);//上级试卷id
        List<AchExamPaperProjectItem> itemList = achExamPaperProjectItemService.list(new QueryWrapper<AchExamPaperProjectItem>(achExamPaperProjectItem));
        //按题型分项依次现在插入
        for (AchExamPaperProjectItem examPaperProjectItem : itemList) {
            for (Object o : paperItemStandardItemArray) {
                JSONObject object = (JSONObject) o;//转换后才能取某一字段
                String itemDomainName = ((JSONObject) o).getString("itemDomainName");
                String itemDomainSubName = ((JSONObject) o).getString("itemDomainSubName");
                String itemDomainScore = ((JSONObject) o).getString("itemDomainScore");
                //分隔分数范围比率 如：itemDomainScore = "0-60",分割切转为浮点型0.0 和 0.6,standItemLowestRate = 0.0   standItemHighestRate = 0.6
                String str[] = itemDomainScore.split("-", 2);
                Double standItemLowestRate = Double.valueOf(str[0]);//取值范围最低比率 如：0.0
                Double standItemHighestRate = Double.valueOf(str[1]);//取值范围最高比率 如：0.6
                //依次给实体的属性set值
                AchAchieveStandardItem achAchieveStandardItem = new AchAchieveStandardItem();
                achAchieveStandardItem.setId(null);//清空id
                achAchieveStandardItem.setAchievementStandardId(standardId);//主要-上级标准
                achAchieveStandardItem.setSubjectId(subjectId);
                achAchieveStandardItem.setExaPapProItemCode(examPaperProjectItem.getId());//主要：题型分项标准时-题项ID，总分标准时-试卷ID
                CODE = CODE + 1;
                achAchieveStandardItem.setStandItemCode(Integer.toString(CODE));
                achAchieveStandardItem.setStandItemName(itemDomainName + "（" + examPaperProjectItem.getExaPapProItemName() + "）");//段位名称
                achAchieveStandardItem.setStandItemAliasname(itemDomainSubName);//段位简称
                //取值范围，根据分项题型的满分
                Double scoreMin = examPaperProjectItem.getExaPapProItemFullMarks() * standItemLowestRate;//主要：计算后得最低比率对应的最低分数
                achAchieveStandardItem.setStandItemLowestScore(scoreMin);
                Double scoreMax = examPaperProjectItem.getExaPapProItemFullMarks() * standItemHighestRate;//主要：计算后得最高比率对应的最高分数
                achAchieveStandardItem.setStandItemHighestScore(scoreMax);
                achAchieveStandardItem.setStandItemLowestRate(standItemLowestRate);//主要：最低比率 如：0.0
                achAchieveStandardItem.setStandItemHighestRate(standItemHighestRate);//主要：最高比率 如：0.6

                achAchieveStandardItem.setStandItemActualScore(null);//实际得分
                achAchieveStandardItem.setStandItSpecialRestrictions(null);//特殊限制（1无限制，2性别，3年级 4年龄，5预留）
                achAchieveStandardItem.setSitemSpecRestMaxvalue(null);//特殊限制数最大值（不含或小于）
                achAchieveStandardItem.setSitemSpecRestMinvalue(null);//特殊限制数最小值（含即大于等于或等于）
                achAchieveStandardItem.setStandItemFatherId("0");//上级项目id
                i = i + 1;
                achAchieveStandardItem.setStandItemOrder(i);//排序
                achAchieveStandardItem.setSysOrgCode(null);//部门编码
                achAchieveStandardItem.setTenantId(tenantId);
                achAchieveStandardItem.setDelFlag(0);
                achAchieveStandardItem.setIzOpen(1);
                boolean _statu = save(achAchieveStandardItem);
                if (!_statu) {
                    return false;
                }
            }
        }
        return true;
    }


    /**
     * 清理废弃数据 （不能跨租户删除）
     * 清理删除全部与标准有关的垃圾数据：全家、清理
     */
    @Override
    public int clearAbandon(){
        //没有标准的关系数据：垃圾数据应该删除
        achAchieveStandardItemMapper.clearAbandon1();
        //没有标准子项的标准包，没有子项的标准包应该被删除，删除1天前的数据，避免误删
        achAchieveStandardItemMapper.clearAbandon2();
        //没有父级标准包的子项：没有父级标准包的子项应该删除
        int clearStatus = achAchieveStandardItemMapper.clearAbandon3();
        return clearStatus;
    }

}
